package path.calculator;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;

import java.util.List;

import org.junit.Before;
import org.junit.Test;

public class PermutationGeneratorTest {
    private PermutationGenerator<String> generator;

    @Before
    public void setup() {
        generator = new PermutationGenerator<String>();
    }

    @Test
    public void noNodesNoPerumtations() {
        List<Permutation<String>> allCombinations = generator.allCombinations();
        assertEquals(0, allCombinations.size());
    }

    @Test
    public void oneNodeOnePermutation() {
        generator.addNode("A");
        List<Permutation<String>> allCombinations = generator.allCombinations();
        assertEquals(1, allCombinations.size());
        assertIsIncluded(allCombinations, "A");
    }

    @Test
    public void twoNodesTwoPerutations() {
        generator.addNode("A");
        generator.addNode("B");
        List<Permutation<String>> allCombinations = generator.allCombinations();
        assertEquals(2, allCombinations.size());
        assertIsIncluded(allCombinations, "A", "B");
        assertIsIncluded(allCombinations, "B", "A");
    }

    @Test
    public void threeNodesSixPermutations() {
        generator.addNode("A");
        generator.addNode("B");
        generator.addNode("C");
        List<Permutation<String>> allCombinations = generator.allCombinations();
        assertEquals(6, allCombinations.size());
        assertIsIncluded(allCombinations, "A", "B", "C");
        assertIsIncluded(allCombinations, "A", "C", "B");
        assertIsIncluded(allCombinations, "B", "A", "C");
        assertIsIncluded(allCombinations, "B", "C", "A");
        assertIsIncluded(allCombinations, "C", "A", "B");
        assertIsIncluded(allCombinations, "C", "B", "A");
    }

    @Test
    public void fourNodesTwentyFourPermutations() {
        generator.addNode("1");
        generator.addNode("2");
        generator.addNode("3");
        generator.addNode("4");
        List<Permutation<String>> allCombinations = generator.allCombinations();
        assertEquals(24, allCombinations.size());
        assertIsIncluded(allCombinations, "1", "2", "3", "4");
        assertIsIncluded(allCombinations, "1", "2", "4", "3");
        assertIsIncluded(allCombinations, "1", "3", "2", "4");
        assertIsIncluded(allCombinations, "1", "3", "4", "2");
        assertIsIncluded(allCombinations, "1", "4", "2", "3");
        assertIsIncluded(allCombinations, "1", "4", "3", "2");

        assertIsIncluded(allCombinations, "2", "1", "3", "4");
        assertIsIncluded(allCombinations, "2", "1", "4", "3");
        assertIsIncluded(allCombinations, "2", "3", "1", "4");
        assertIsIncluded(allCombinations, "2", "3", "4", "1");
        assertIsIncluded(allCombinations, "2", "4", "1", "3");
        assertIsIncluded(allCombinations, "2", "4", "3", "1");

        assertIsIncluded(allCombinations, "3", "1", "2", "4");
        assertIsIncluded(allCombinations, "3", "1", "4", "2");
        assertIsIncluded(allCombinations, "3", "2", "1", "4");
        assertIsIncluded(allCombinations, "3", "2", "4", "1");
        assertIsIncluded(allCombinations, "3", "4", "1", "2");
        assertIsIncluded(allCombinations, "3", "4", "2", "1");

        assertIsIncluded(allCombinations, "4", "1", "2", "3");
        assertIsIncluded(allCombinations, "4", "1", "3", "2");
        assertIsIncluded(allCombinations, "4", "2", "1", "3");
        assertIsIncluded(allCombinations, "4", "2", "3", "1");
        assertIsIncluded(allCombinations, "4", "3", "1", "2");
        assertIsIncluded(allCombinations, "4", "3", "2", "1");
    }

    private void assertIsIncluded(List<Permutation<String>> allCombinations, String... values) {
        assertTrue(allCombinations.contains(new Permutation<String>(values)));
    }
}
